/**
 * @description ajax服务
 * @author Rid King
 * @since 2018-07-06
 */

import objecter from '../../../objecter/2.0.0/js/objecter'
import urler from '../../../urler/2.0.0/js/urler'
import Service from '../../../service/2.0.0/js/service'

/**
 * @class ajax服务类
*/
class AjaxService extends Service {
  /**
   * @desc 发送请求
   * @param options <Object> 配置
   * @return <Promise>
   * */
  _send (options) {
    let me = this
    // 复制配置
    options = objecter.clone(options)
    // 是否超时
    let isTimeout = false
    // 请求参数
    let params =  ''

    // 如果是GET请求，拼接url
    if (/get/i.test(options.method)) {
      if (options.data) {
        let query = urler.stringify(options.data)
        options.url += query ? '?' + query : ''
      }
      options.data = ''
    } else {
      // 数据为数组格式时，请求设置为json
      if (Array.isArray(options.data)) {
        options.headers['Content-Type'] = 'application/json;charset=UTF-8'
      }
      else if (objecter.isObject(options.data)) {
        // 检查数据中是否含有对象
        let hasObject = false
        for (let key in options.data) {
          if (objecter.isObject(options.data[key])) {
            hasObject = true
            break
          }
        }
        // 数据中含有对象
        if (hasObject) {
          options.headers['Content-Type'] = 'application/json;charset=UTF-8'
        }
      }

      // 参数设置
      if (options.data) {
        if (/json/.test(options.headers['Content-Type'])) {
          params = JSON.stringify(options.data)
        } else {
          params = urler.stringify(options.data)
        }
      }
      options.body = params
    }

    return new Promise((resolve, reject) => {
      // 创建 - 非IE6 - 第一步
      let xhr = this._getXHR()
      // 是否跨域
      let withCredentials = String(options.withCredentials)
      xhr.withCredentials = (withCredentials === 'true' || withCredentials === '1') ? true : false
      // 开始时间
      let start = new Date().getTime()
      // 接收 - 第三步
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          // 结束时间
          let end = new Date().getTime()
          let status = xhr.status
          // 超时检测
          if (isTimeout) {
            return false
          }
          if (status >= 200 && status <= 304) {
            resolve({
              options: options,
              status: status,
              responseText: xhr.responseText,
              response: me.parse(xhr.responseText, options.dataType, options.isForceParse),
              xhr: xhr,
              start, end
            })
          } else {
            // error可能在的值"timeout", "error", "notmodified"，"parsererror"
            reject({
              options: options,
              status: status,
              responseText: xhr.responseText,
              response: me.parse(xhr.responseText, options.dataType, options.isForceParse),
              xhr: xhr,
              start, end
            })
          }

          // 结束回调
          if (typeof options.complete === 'function') {
            options.complete({
              options: options,
              status: status,
              responseText: xhr.responseText,
              response: me.parse(xhr.responseText, options.dataType, options.isForceParse),
              xhr: xhr,
              start, end
            })
          }
        }
      }

      // 连接 和 发送 - 第二步
      if (/^\/\//.test(options.url)) {
        let protocol = options.protocol || location.protocol
        if (/file/.test(protocol)) {
          protocol = 'http:'
        }
        options.url = protocol + options.url
      }
      if (/^get$/i.test(options.method)) {
        xhr.open(options.method, options.url, options.async)
        //设置表单提交时的内容类型
        Object.keys(options.headers).forEach((key) => {
          xhr.setRequestHeader(key, options.headers[key])
        })
        xhr.send(null)
      } else {
        xhr.open(options.method, options.url, options.async)
        //设置表单提交时的内容类型
        Object.keys(options.headers).forEach((key) => {
          xhr.setRequestHeader(key, options.headers[key])
        })
        // 发送
        xhr.send(params || null)
      }

      //超时处理
      if (options.timeout > 50) {
        // 结束时间
        let end = new Date().getTime()
        let timer = setTimeout(function () {
          if (xhr.readyState !== 4) {
            isTimeout = true
            xhr.abort()
            clearTimeout(timer)
          }
          reject({
            xhr, options,
            error: 'Timeout',
            start, end
          })
        }, options.timeout)
      }
    })
  }

  /**
   * @function 获取异步请求对象
   * @return {XMLHttpRequest}
  */
  _getXHR () {
    let xhr = null
    if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest()
    } else { // IE6及其以下版本浏览器
      xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }

    return xhr
  }

  /**
   * @function 默认配置
   * @return {Object}
  */
  getDefaults () {
    /**
     * 默认配置
     * {
     *  url : <String>, 访问地址
     *  method : <String>, 访问类型，GET, POST, PUT, DELETE, HEAD
     *  data : <Object>, 数据
     *  body : <ArrayBuffer, ArrayBufferView(Uint8Array and friends), Blob/File, String, URLSearchParams, FormData>, 传输的数据
     *  dataType : <String>, 返回值类型
     *  headers : <Object>, 关联的Header对象
     *  cache : <String>, 缓存模式(default, reload, no-cache)
     *  timeout: <Int>, // 超时时间，默认-1永不过期
     *  async: {Boolean} // 是否异步步，默认true
     * }
    */
    return {
      url: '',
      method: 'POST',
      data: '',
      timeout: -1, // 默认-1永不过期
      async: true,
      dataType: 'object',
      isForceParse: false, // 是否强制转换
      // 请求头对象
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
      },
      // 跨域携带cookie
      crossDomain: true,
      // 是否跨域
      withCredentials: false
    }
  }
}

const ajaxService = new AjaxService
export default AjaxService
export {
  ajaxService
}